package com.tedu.api.io;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import com.tedu.api.io.IOExcepti;
import org.junit.Test;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * RandomAccessFile解决：File无法实现读写操作
 *
 * RandomAccessFile类  随机访问文件类
 * 功能：实现“文件”、文件夹的读写操作，底层使用C语言，底层：二进制数据
 *
 * 创建随机访问文件夹
 * RandomAccessFile raf=new RandomAccessFile("路径+文件全称","rw");
 * RandomAccessFile raf=new RandomAccessFile("路径+文件全称","r");
 * 第二个参数[mode 模式]：r 模式--->该文件可以读操作
 *                     rw 模式--->该文件可以读写操作
 * 需求：实现 CV 复制音乐/视频
 */
public class RandomAccessFileAPI {
    @Test
    public void testRAF() throws IOException {
        //RandomAccessFile对象创建出来---路径+全称  |  模式："rw"
        RandomAccessFile raf =
                new RandomAccessFile("raf.txt", "rw");
        //1.在API项目文件下 创建 raf.txt 文件，并且实现读写操作

        //计算机 识别：二进制   0000 0000
        /**
         * 需要往raf.txt 写出一个 a 字母
         * write(整数)
         * 作用：往文件中写出一个字节,抛出IO流异常：存在写出失败情况
         *      整数的低八位写到文件中
         *
         *    1字节==8位二进制      0000 0001          1
         *                        0000 0010          2
         *                        0000 0011          3
         *                        0000 0110          6
         *    1024
         */
        raf.write(97); //写出一个字节，识别二进制，写十进制转二进制
        raf.write(98);
        raf.write(101);
        //write方法---一个字节一个字节写出
        //关闭流   close()
        raf.close();
    }

    /**
     * read()
     * 作用：读取一个字节，返回十进制int类型返回，如果文件读到-1，代表结束
     */
    @Test
    public void testRead() throws IOException {
        //创建对象：随机访问文件对象---只读---raf.txt文件的内容
        RandomAccessFile raf =
                new RandomAccessFile("raf.txt", "r");
        int i = raf.read();   //"a" ---ASCII码---97
        int j = raf.read();
        int k = raf.read();
        int y = raf.read();
        System.out.println(i + " " + j + " " + k + " " + y);
    }

    /**
     * RAF类---构造器实现：读写操作--
     * -write(数值) read() 一个字节一个字节写出以及读入
     * 需求：复制粘贴一个音乐 【version 1--不考虑效率】
     */
    @Test
    public void testCV() throws IOExcepti

    on {
        //1.源文件--“小跳蛙.mp3”--复制--  操作：读入
        RandomAccessFile src = null;
        try {
            src = new RandomAccessFile("小跳蛙.mp3", "r");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //2.复制文件--”新跳蛙.mp3“---粘贴---操作：写出
        RandomAccessFile desc =
                null;
        try {
            desc = new RandomAccessFile("新跳蛙.mp3", "rw");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //3.用于保存读取到字节；①保存一个字节 ②-1代表文件读取到末尾
        int data = -1;
        //4.一直从“小跳蛙.mp3”中一个字节一个字节读取---[true]
        //(date=src.read())!=-1      条件判断语句[true]
        long start = System.currentTimeMillis();
        //获取到当前系统时间毫秒数
        while ((data = src.read()) != -1) { //一个字节一个字节--读
            //同时一个字节一个字节写出“新跳蛙.mp3”
            desc.write(data);
        }
        long end = System.currentTimeMillis();
        System.out.println("复制粘贴花费多少：" + (end - start) / 1000 + "秒");
    }

    /**
     * 需求：复制粘贴一个音乐 【version 2--考虑效率】
     * 一个字节一个字节读取---一个字节一个字节写出【慢】
     * 100kb读取---100kb写出   【快】
     */
    @Test
    public void testCVS() throws IOException {
        //1.从API目录下“小跳蛙.mp3”--读取数据【100KB】
        RandomAccessFile src = new RandomAccessFile("小跳蛙.mp3", "r");
        //2.从API目录下写出"效率高.mp3"---写出数据【100kb】
        RandomAccessFile desc = new RandomAccessFile("效率高.mp3", "rw");
        //3.保存每次读取字节量:①覆盖：保存读写数据，保障数据稳定
        //                  ②没有数据：表示文件读取到末尾
        int len = -1;
        //4.效率：100KB    字节数组： byte
        byte[] data = new byte[1024 * 100]; //100KB
        //5.一直  从src文件中读取数据：100KB  |   read(byte[] b) 读100KB
        //5.1 src.read()   从src”小跳蛙.mp3“一个字节一个字节读
        //5.2 src.read(byte[] data)    从src”小跳蛙.mp3“  100KB的读
        //5.3 len=src.read(byte[] data) 保存从src"小跳蛙.mp3"100KB的读
        //5.4 (len=src.read(byte[] data))!=-1   【反复判断条件】
        //     将读到的100KB的字节数据保存len中,只要不等于-1，没有读完，一直读
        long start = System.currentTimeMillis();
        while ((len = src.read(data)) != -1) {
        }
        //  同时,读文件同时，写出数据write
        //  write(整数) 写出一个字节【慢】
        //  write(字节数组,0,-1) 写出字节数组指定的单位量【例：100kb】
        desc.write(data, 0, len);
    }

    long end = System.currentTimeMillis();

    /**
     * 需求：利用标准流实现视频复制粘贴
     */
    @Test
    public void testCV() throws IOException {
        //1.从”复制文件.mp4“ 复制 操作---读入
        FileInputStream fis = new FileInputStream("复制文件.mp4");
        //2.创建新文件”复制文件.mp4“ 粘贴 操作---写出
        FileOutputStream fos = new FileOutputStream("新文件.mp4");
        //3.保存每次读取的数据【字节量--int】
        int len = -1;
        //4.一直 从”复制文件.mp4“进行读入操作，不等于-1  一直读
        //(len=fis.read())!=-1
        while ((len = fis.read()) != -1) {//true
            //4.1同时 写出”新文件.mp4“
            fos.write(len);
        }
        //5.关闭流     ---测：效率低--正常播放
        fis.close();
        fos.close();
    }

    /**
     * 需求：利用标准流实现视频复制粘贴--效率低
     * 效率高--->控件之行为：自定100KB
     * <p>
     * 【高级流】BufferedInputStream  缓冲输入流---提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     * BufferedOutputStream  缓冲输出流---提高效率--缓冲区： 字节数组【长度按照文件大小合理分配】
     * 高级流使用方式：①处理低级流，套在低级流上
     * ②直接使用高级流的方法
     * ③高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS() throws IOException {
        //创建低级流：读入”复制视频.mp4“
        FileInputStream fis =
                new FileInputStream("复制视频.mp4");
        //1.创建高级流：套在低级流上【自带缓冲区：字节数组】
        BufferedInputStream bis = new BufferedInputStream(fis);

        //2.创建低级流：“写出高效视频.mp4”
        FileOutputStream fos =
                new FileOutputStream("搞笑视频.mp4");
        //2.创建高级流：套在低级流上【自带缓冲区：字节数组】
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        //3.保存数据
        int len = -1;
        //4.高级流--低级流方法一致---read()读取内嵌缓冲区【字节数组】
        //  高级流--低级流方法一致---write()写出内嵌缓冲区【字节数组】
        //一直从“复制视频.mp4”读取数据，不等于-1，一直读
        //(len=bis.read())！=-1
        long start = System.currentTimeMillis();//系统时间毫秒数
        while ((len = bis.read()) != -1) {
            bos.write(len);
        }
        long end = System.currentTimeMillis();
        System.out.println("缓冲流【自带缓冲区】" + (end - start) + "毫秒数");
        //关闭流---高级流与低级流：都关--->高级流间接性关闭低级流
        bis.close();  //高级流--缓冲输入流
        bis.close();  //高级流--缓冲输入流
        bis.close();  //低级流--文件输入流


    }
/**
 *
 * 高级流---缓冲流 【内嵌缓冲流】
 * BufferedOutpuStream    缓冲输出流
 * 需求；通过缓冲输出流 实现 从程序中文件
 */
@Test
public void testBOS() throws IOException {
 //1.0 创建低级流 ---bos.txt
 FileOutputStream fos= new FileOutputStream("bos,txt");
  //2.0 创建高级流---缓冲区；字节数组--合理【传输效率】
 BufferedOutputStream bos=new BufferedOutputStream(fos);
 //3.0 写出文本内容
 String str="50";
 //4.0写出列bos.txt 文件中；字符串 转化成字节数组
 bos.write(str.getBytes());
//5.0 将缓冲区数据一次性写出  flush()   [立即写出】
 //bos.flush();
    bos.flush();
bos.close();    //关闭流----一定把缓冲区数据 全部写出












}











}